home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.sources.misc
- From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
- Subject: v06i099: Happy birthday to you...
- Reply-To: rsalz@bbn.com (Rich Salz)
-
- Posting-number: Volume 6, Issue 99
- Submitted-by: rsalz@bbn.com (Rich Salz)
- Archive-name: bday
-
-
- There used to be a machine called oz.ai.mit.edu, and it used to have a
- wizard who knew when it was your birthday. He was a friendly wizard, not
- at all deserving of the name "daemon," because he'd send you a nice little
- note when that special day came around...
-
- I had been saving one of my messages for some time, but only just now got
- around to writing this program. It reads a file with email names and
- birthdays, and sends mail. It should be run out of cron early every
- morning. If WEEKEND_HACK is #define'd, then on Friday bday will send mail
- to people with birthdays on Saturday and Sunday.
-
- The program uses getopt and sendmail, but hacking around the latter should
- be pretty easy.
-
- /rich $alz
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 1 (of 1)."
- # Contents: MANIFEST Makefile README bday.8 bday.c bdaylist bdaymesg
- # Wrapped by rsalz@papaya.bbn.com on Mon May 8 11:17:21 1989
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'MANIFEST' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'MANIFEST'\"
- else
- echo shar: Extracting \"'MANIFEST'\" \(459 characters\)
- sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
- X File Name Archive # Description
- X-----------------------------------------------------------
- X MANIFEST 1 This shipping list
- X Makefile 1 Makefile for birthday greetings
- X README 1 Random stuff
- X bday.8 1 Manual page
- X bday.c 1 Send birthday greetings to users
- X bdaylist 1 Control file for bday
- X bdaymesg 1 Message file for bday
- END_OF_FILE
- if test 459 -ne `wc -c <'MANIFEST'`; then
- echo shar: \"'MANIFEST'\" unpacked with wrong size!
- fi
- # end of 'MANIFEST'
- fi
- if test -f 'Makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Makefile'\"
- else
- echo shar: Extracting \"'Makefile'\" \(489 characters\)
- sed "s/^X//" >'Makefile' <<'END_OF_FILE'
- X##
- X## Makefile for birthday greetings.
- X## Written by Rich $alz, <rsalz@bbn.com>. This package has no copyright.
- X## $Header: Makefile,v 1.1 89/05/08 11:07:14 rsalz Exp $
- X##
- X
- XCFLAGS = -O
- X
- Xall: bday bday.8
- X
- Xinstall: all
- X @echo "Install according to local convention"
- X
- Xclean:
- X rm -f foo core SHAR tags lint a.out *.o bday
- X
- Xbday: bday.c
- X @rm -f bday
- X $(CC) -o bday $(CFLAGS) bday.c
- X
- X## I know it fits in one kit, so...
- Xkit:
- X @rm -f SHAR
- X makekit -m
- X @rm -f MANIFEST.BAK
- X @mv Part01 SHAR
- END_OF_FILE
- if test 489 -ne `wc -c <'Makefile'`; then
- echo shar: \"'Makefile'\" unpacked with wrong size!
- fi
- # end of 'Makefile'
- fi
- if test -f 'README' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'README'\"
- else
- echo shar: Extracting \"'README'\" \(699 characters\)
- sed "s/^X//" >'README' <<'END_OF_FILE'
- X
- XThere used to be a machine called oz.ai.mit.edu, and it used to have a
- Xwizard who knew when it was your birthday. He was a friendly wizard, not
- Xat all deserving of the name "daemon," because he'd send you a nice little
- Xnote when that special day came around...
- X
- XI had been saving one of my messages for some time, but only just now got
- Xaround to writing this program. It reads a file with email names and
- Xbirthdays, and sends mail. It should be run out of cron early every
- Xmorning. If WEEKEND_HACK is #define'd, then on Friday bday will send mail
- Xto people with birthdays on Saturday and Sunday.
- X
- XThe program uses getopt and sendmail, but hacking around the latter should
- Xbe pretty easy.
- X
- X /r$
- END_OF_FILE
- if test 699 -ne `wc -c <'README'`; then
- echo shar: \"'README'\" unpacked with wrong size!
- fi
- # end of 'README'
- fi
- if test -f 'bday.8' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'bday.8'\"
- else
- echo shar: Extracting \"'bday.8'\" \(1936 characters\)
- sed "s/^X//" >'bday.8' <<'END_OF_FILE'
- X.\" $Header: bday.8,v 1.1 89/05/08 11:07:38 rsalz Exp $"
- X.TH BDAY 8
- X.SH NAME
- Xbday \- birthday daemon
- X.SH SYNOPSIS
- X.B bday
- X[
- X.BI \-b birthdays
- X] [
- X.BI \-m message
- X] [
- X.BI \-r report_to
- X] [
- X.BI \-s sendmail_cmd
- X]
- X.SH DESCRIPTION
- X.I Bday
- Xis a program intended to be run every day out of
- X.IR cron (1).
- XIt reads a file containing a list of user names and birthdays,
- Xand sends a message to anyone whose birthday is today.
- XThe ``\-r'' option may be used to specify a person who should receive
- Xa report whenever a greeting is sent.
- X.PP
- XThe ``\-b'' option may be used to specify the file containing the list
- Xof people's birthdays; the default is
- X.IR /usr/adm/bdaylist .
- XThis file should consist of a series of lines of three fields, each separated
- Xby whitespace:
- X.RS
- X.nf
- X.ta \w'#emailname 'u +\w'month 'u
- X#emailname month day
- Xrsalz 2 10
- X.fi
- X.RE
- XThe first column is the name of the person to send the email message to.
- XThe second column is the month in which the person's birthday occurs;
- X1 is for January, and so on up to 12 for December.
- XThe third column is the day of the month on which their birthday occurs.
- XBlank lines, and any text after a pound sign is ignored.
- X.PP
- XThe ``\-m'' option may be used to specify the file with the birthday message;
- Xthe default is
- X.IR /usr/adm/bdaymesg .
- XThis is useful, for example, to send different greetings to people who's
- Xbirthday falls on a weekend.
- X.PP
- XThe command used to send the mail may be changed by giving the ``\-s''
- Xoption; this is useful for debugging.
- XNote that the details of sending the message (such as the mail headers)
- Xare compiled into the code, but that's okay because this is just a short
- Xfun hack, anyhow.
- X.SH AUTHOR
- XWritten by Rich $alz, <rsalz@bbn.com>, after receiving just such a message
- Xfrom one of the machine at MIT. This package has no copyright.
- X.SH FILES
- X.ta \w'/usr/adm/bdaylist 'u
- X/usr/adm/bdaylist Default birthday list
- X/usr/adm/bdaymesg Default birthday message
- END_OF_FILE
- if test 1936 -ne `wc -c <'bday.8'`; then
- echo shar: \"'bday.8'\" unpacked with wrong size!
- fi
- # end of 'bday.8'
- fi
- if test -f 'bday.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'bday.c'\"
- else
- echo shar: Extracting \"'bday.c'\" \(6081 characters\)
- sed "s/^X//" >'bday.c' <<'END_OF_FILE'
- X/*
- X** When you care enough to send the very best....
- X** Written by Rich $alz, <rsalz@bbn.com>, after seeing the MIT program
- X** in action. This package has no copyright.
- X*/
- X#include <stdio.h>
- X#include <ctype.h>
- X#include <sys/types.h>
- X#include <time.h>
- X#include <fcntl.h>
- X#include <sgtty.h>
- X#ifndef lint
- X#ifndef SABER
- Xstatic char RCS[] =
- X "$Header: bday.c,v 1.1 89/05/08 11:13:22 rsalz Exp $";
- X#endif /* SABER */
- X#endif /* lint */
- X
- X/* Compilation control. */
- X#define STRCHR strchr /* Maybe index */
- X#define STRRCHR strrchr /* Maybe rindex */
- X#undef WEEKEND_HACK /* Work harder on Friday? */
- X
- X/* Manifest constants. */
- X#define TRUE 1
- X#define FALSE 0
- X#define LEN 128
- X#define FROM "The Birthday Wizard <wizard@pineapple.bbn.com>"
- X
- X/* Syntactic sugar. */
- X#define WHITE(c) ((c) == ' ' || (c) == '\t')
- X#define Fprintf (void)fprintf
- X#ifdef lint
- X#undef putc
- X#endif /* lint */
- X
- X
- X/* Global data. */
- Xstatic char *progname;
- Xstatic char *ReportTo = NULL;
- Xstatic char *Birthdays = "/usr/adm/bdaylist";
- Xstatic char *Message = "/usr/adm/bdaymesg";
- Xstatic char *sendmail = "/usr/lib/sendmail.sun -t -oi";
- X/*static char *sendmail = "/usr/lib/sendmail -t -oi"; */
- X
- X
- X/* Linked in later. */
- Xextern int errno;
- Xextern char *optarg;
- Xextern time_t time();
- Xextern char *sprintf(); /* Too painful, my ass */
- Xextern char *strcpy();
- Xextern char *STRCHR();
- Xextern char *STRRCHR();
- X
- X
- X/*
- X** Return the text string that corresponds to errno.
- X*/
- Xstatic char *
- Xstrerror(e)
- X int e;
- X{
- X extern int sys_nerr;
- X extern char *sys_errlist[];
- X static char buff[30];
- X
- X if (e > 0 && e < sys_nerr)
- X return sys_errlist[e];
- X (void)sprintf(buff, "Error code %d", e);
- X return buff;
- X}
- X
- X
- X/*
- X** Send mail to the person.
- X*/
- Xstatic void
- XDoit(Name)
- X char *Name;
- X{
- X register FILE *F;
- X register FILE *M;
- X register int c;
- X
- X /* Prep the pipe. */
- X if ((F = popen(sendmail, "w")) == NULL) {
- X Fprintf(stderr, "%s: Doit(%s) failed to popen \"%s\", %s.\n",
- X progname, Name, sendmail, strerror(errno));
- X return;
- X }
- X
- X /* Write headers. */
- X Fprintf(F, "From: %s\n", FROM);
- X Fprintf(F, "To: %s\n", Name);
- X Fprintf(F, "Subject: Happy birthday!\n");
- X Fprintf(F, "\n");
- X
- X /* Feed in the message. */
- X if (M = fopen(Message, "r")) {
- X while ((c = getc(M)) != EOF)
- X (void)putc(c, F);
- X (void)fclose(M);
- X }
- X
- X /* Close up. Done? */
- X (void)pclose(F);
- X if (ReportTo == NULL)
- X return;
- X
- X /* Report it. */
- X if ((F = popen(sendmail, "w")) == NULL) {
- X Fprintf(stderr, "%s: Doit(%s) couldn't report, %s.\n",
- X progname, Name, strerror(errno));
- X return;
- X }
- X
- X /* Write the report. */
- X Fprintf(F, "To: %s\n", ReportTo);
- X Fprintf(F, "Subject: Greetings sent\n");
- X Fprintf(F, "\n");
- X Fprintf(F, "Sent a message to %s.\n", Name);
- X
- X /* Close up. Definitely done. */
- X (void)pclose(F);
- X}
- X
- X
- X/*
- X** Return pointer to first non-whitespace.
- X*/
- Xstatic char *
- XSkip(p)
- X register char *p;
- X{
- X while (*p && WHITE(*p))
- X p++;
- X return p;
- X}
- X
- X
- X/*
- X** Check the list in the file for birthdays.
- X*/
- Xstatic void
- XScanForWork(ThisMonth, ThisDay)
- X int ThisMonth;
- X int ThisDay;
- X{
- X register FILE *F;
- X register char *p;
- X int UserMonth;
- X int UserDay;
- X char UserName[LEN];
- X char buff[LEN];
- X
- X /* Open the list of birthdays. */
- X if ((F = fopen(Birthdays, "r")) == NULL) {
- X Fprintf(stderr, "%s: ScanForWork can't open \"%s\" for reading, %s.\n",
- X progname, Birthdays, strerror(errno));
- X return;
- X }
- X
- X /* Scan all lines. */
- X while (fgets(buff, sizeof buff, F)) {
- X /* Clobber comment markers and newlines. */
- X if (p = STRCHR(buff, '#'))
- X *p = '\0';
- X if (p = STRCHR(buff, '\n'))
- X *p = '\0';
- X
- X /* Skip blank or comment lines. */
- X if (buff[0] == '\0')
- X continue;
- X
- X /* First field is the user name. */
- X for (p = buff; *p && !WHITE(*p); p++)
- X ;
- X *p++ = '\0';
- X (void)strcpy(UserName, buff);
- X if (UserName[0] == '\0')
- X continue;
- X
- X /* Second field is the month of the user's birthday. */
- X p = Skip(p);
- X if (*p == '\0')
- X continue;
- X for (UserMonth = atoi(p); *p && isdigit(*p); p++)
- X ;
- X if (UserMonth == 0)
- X continue;
- X
- X /* Third field is the date of the user's birthday. */
- X p = Skip(p);
- X if (*p == '\0')
- X continue;
- X UserDay = atoi(p);
- X if (UserDay == 0)
- X continue;
- X
- X /* Is this one for us? */
- X if (UserMonth == ThisMonth && UserDay == ThisDay)
- X Doit(UserName);
- X }
- X
- X (void)fclose(F);
- X}
- X
- X
- X/*
- X** Make sure the file was specified and is readable.
- X*/
- Xstatic void
- XCheckFile(Name, Purpose)
- X char *Name;
- X char *Purpose;
- X{
- X FILE *F;
- X
- X if (Name == NULL) {
- X Fprintf(stderr, "%s: No %s file given.\n", progname, Purpose);
- X exit(1);
- X }
- X
- X if ((F = fopen(Name, "r")) == NULL) {
- X Fprintf(stderr, "%s: Can't open \"%s\" for %s, %s.\n",
- X progname, Name, Purpose, strerror(errno));
- X exit(1);
- X }
- X
- X (void)fclose(F);
- X}
- X
- X
- Xmain(ac, av)
- X int ac;
- X char *av[];
- X{
- X int i;
- X time_t t;
- X struct tm *tm;
- X char *p;
- X
- X /* Parse JCL. */
- X progname = (p = STRRCHR(av[0], '/')) ? p + 1 : av[0];
- X while ((i = getopt(ac, av, "b:m:r:s:")) != EOF)
- X switch (i) {
- X default:
- X Fprintf(stderr, "Usage:\n\t%s %s\n",
- X progname,
- X "[-b list] [-m message] [-s sendcmd] [-r admin]");
- X exit(1);
- X case 'b':
- X Birthdays = optarg;
- X break;
- X case 'm':
- X Message = optarg;
- X break;
- X case 'r':
- X ReportTo = optarg;
- X break;
- X case 's':
- X sendmail = optarg;
- X break;
- X }
- X
- X /* Make sure the user gave us readable files. */
- X CheckFile(Birthdays, "birthday list");
- X CheckFile(Message, "message");
- X
- X /* What time is it? */
- X t = time((time_t *)NULL);
- X tm = localtime(&t);
- X ScanForWork(tm->tm_mon + 1, tm->tm_mday);
- X
- X#ifdef WEEKEND_HACK
- X /* If it's Friday, check for Saturday and Sunday birthdays. */
- X if (tm->tm_wday == 5) {
- X /* This is easy/sleazy, we avoid checking for end of month... */
- X t += 24 * 60 * 60;
- X tm = localtime(&t);
- X ScanForWork(tm->tm_mon + 1, tm->tm_mday);
- X t += 24 * 60 * 60;
- X tm = localtime(&t);
- X ScanForWork(tm->tm_mon + 1, tm->tm_mday);
- X }
- X#endif /* WEEKEND_HACK */
- X
- X exit(0);
- X}
- END_OF_FILE
- if test 6081 -ne `wc -c <'bday.c'`; then
- echo shar: \"'bday.c'\" unpacked with wrong size!
- fi
- # end of 'bday.c'
- fi
- if test -f 'bdaylist' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'bdaylist'\"
- else
- echo shar: Extracting \"'bdaylist'\" \(227 characters\)
- sed "s/^X//" >'bdaylist' <<'END_OF_FILE'
- X## Data file for birthday program. Written by rsalz@bbn.com; this package
- X## has no copyright.
- X## $Header: bdaylist,v 1.1 89/05/08 11:07:48 rsalz Exp $
- X## Data lines look like this:
- X##email month day
- Xrsalz@bbn.com 2 10
- END_OF_FILE
- if test 227 -ne `wc -c <'bdaylist'`; then
- echo shar: \"'bdaylist'\" unpacked with wrong size!
- fi
- # end of 'bdaylist'
- fi
- if test -f 'bdaymesg' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'bdaymesg'\"
- else
- echo shar: Extracting \"'bdaymesg'\" \(2880 characters\)
- sed "s/^X//" >'bdaymesg' <<'END_OF_FILE'
- X
- X YY
- X YYYY YY
- XHHHHH HHHHH YYY YYYY
- XHHHHH HHHHH PP PPPPPP YYY YYY
- X HHH HHH PPP PP YYY YYY
- X HHH HHH AAAAA PP PPPPPP PP PP YYY YYY
- X HHH HHH AAAAAAA PPP PP PP PP YYY YYY
- X HHH HHH AA AA PP PP PP PP YYY YYY
- X HHH HHH AA AA PP PP PPPPPPP YYYYY
- X HHHHHHHHHHHHHHH AA AA PP PP PP YYYY
- X HHHHHHHHHHHHHHH AA AA PPPPPPP PP YYYY -------
- X HHHHHHHHHHHHHHH AAAAAAAAA PP PP YYYY -------
- X HHH HHH AAAAAAAAA PP PP YYYY -------
- X HHH HHH AA AA PP PP YYYY
- X HHH HHH AA AA PP PP YYYY
- X HHH HHH AA AA PP PP YYYYYY
- X HHH HHH AA AA PP PP YYYYYYY
- X HHH HHH PP PP YYYYYYY
- XHHHHH HHHHH PP PP YYYYYYY
- XHHHHH HHHHH PP PP YYYYYYY
- X YYYYY
- XBBBBBBBBBBBBB YYY
- XBBBBBBBBBBBBBB Y
- X BBBB BBB II YYY YYY
- X BB BB II DDDDDDDDDDDDD YYYY YYYY
- X BB BB DDDDDDDDDDDDDD YY YY
- X BB BB III RRR RRRR DDD DDD A YY YY
- X BB BB II RRRR RR DDD DDD AAA YY YY
- X BB BBB II RRR DDD DDD AAAAA YY YY
- X BBB BBBB II RR DDD DDD AAAAAAA YY YY
- X BBBBBBBBBBB II RR DDD DDD AA AA YY YY
- X BBBBBBBBB II RR DDD DDD AA AA YYYY
- X BBBBBBBBBBB II RR DDD DDD AAAAAAAAA YYY
- X BBB BBBB IIII RRRR DDD DDD AAAAAAAAA YYY
- X BB BBB HHH DDD DDD AA AA YYY
- X BB BBB TT HHHH DDD DDD AA AA YYY
- X BB BBB TT HH DDD DDD AA AA YYY
- X BB BBB TTTTTT HH DDD DDD AA AA YYY
- X BB BBB TT HH DDD DDD YYY
- X BB BBB TT HHHHHHHH DDDDDDDDDDDDD YYY
- X BB BBB TT HH HH DDDDDDDDDDDD YYYY
- X BBBB BBBB TT HH HH YYYY
- XBBBBBBBBBBBBBBB TT TT HH HH YYYYYYYYYYYYYYYYYYYYYYYYYY
- XBBBBBBBBBBBBBB TTTT HH HH YYYYYYYYYYYYYYYYYYYYYYYY
- X HHHH HHHH YYYYYYYYYYYYYYYYYYYYYY
- END_OF_FILE
- if test 2880 -ne `wc -c <'bdaymesg'`; then
- echo shar: \"'bdaymesg'\" unpacked with wrong size!
- fi
- # end of 'bdaymesg'
- fi
- echo shar: End of archive 1 \(of 1\).
- cp /dev/null ark1isdone
- MISSING=""
- for I in 1 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have the archive.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-
-